package gui;

import image.Layer;

import java.awt.Point;
import java.util.ArrayList;
import java.util.Collection;

import com.sun.javafx.scene.control.skin.LabeledText;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.Label;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Ellipse;
import javafx.scene.shape.Line;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.Shape;

/**
 * A class that holds settings which the user set
 * @author Etienne Bruines
 * @author Bas Dobbelsteen
 */
public class Settings 
{
	private boolean showToolbar;
	private boolean showRuler;
	private ObjectProperty<Mode> currentMode;
	private boolean isDragging;
	
	private ArrayList<Point> trianglePoints;
	
	/**
	 * The location at which the drawing began - should be NULL whenever isDragging == false
	 */
	private Point startPoint;
	private Shape selectionShape;
	
	private Paint foreColor = Color.BLACK;
	private Paint backColor = Color.BLUE;
	
//	private static final Color SELECTION_COLOR = Color.GRAY;
	private static final Color DRAW_COLOR= Color.DARKGRAY;
	
	public Settings()
	{
		currentMode = new SimpleObjectProperty<Mode>();
		currentMode.set(Mode.Static);
		trianglePoints = new ArrayList<Point>();
		strokeWidth = new SimpleDoubleProperty(2.0);
		
		strokeWidth.addListener(new ChangeListener<Number>() { 
			@Override public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue)
			{
				if (getMode() == Mode.Modify)
				{
					if (Main.getImageManager().getActiveImage().getActiveLayer() != null)
						Main.getImageManager().getActiveImage().getActiveLayer().setStroke(newValue.doubleValue());
				}
			}
		});
	}
	
	// ============
	// Setters
	// ============
	
	public void setShowToolbar(boolean b)
	{
		showToolbar = b;
	}
	
	public void setShowRuler(boolean b)
	{
		showRuler = b;
	}
	
	public void setMode(Mode m)
	{
		currentMode.set(m);
	}
	
	public void startDragging(Point start)
	{
		isDragging = true;
		startPoint = start;
	}
	
	public void stopDragging()
	{
		isDragging = false;
		startPoint = null;
	}
	
	public void setForeColor(Color c)
	{
		if (getMode() == Mode.Modify)
		{
			if (Main.getImageManager().getActiveImage().getActiveLayer() != null)
				Main.getImageManager().getActiveImage().getActiveLayer().setBorder(c);
		}
		foreColor = c;
	}
	
	public void setBackColor(Color c)
	{
		if (getMode() == Mode.Modify)
		{
			if (Main.getImageManager().getActiveImage().getActiveLayer() != null)
				Main.getImageManager().getActiveImage().getActiveLayer().setBackground(c);
		}
		backColor = c;
	}
	
	// ============
	// Getters
	// ============
	
	public boolean isShowToolbar()
	{
		return showToolbar;
	}
	
	public boolean isShowRuler()
	{
		return showRuler;
	}
	
	public Mode getMode()
	{
		return currentMode.get();
	}
	
	public ObjectProperty<Mode> modeProperty()
	{
		return currentMode;
	}
	
	public boolean isDragging()
	{
		return this.isDragging;
	}
	
	/**
	 * Gets the point where the dragging started - can be NULL if not dragging
	 * @return
	 */
	public Point getStartPoint()
	{
		return startPoint;
	}
	
	public void setTarget(Layer l)
	{
		targetL = l;
	}
	private Layer targetL;
	public Layer getTarget()
	{
		return targetL;
	}
	
	private int dragCounter = 0;
	public void clearCounter()
	{
		dragCounter = 0;
	}
	public int getCount()
	{
		return dragCounter;
	}
	public void setCounterPlusOne()
	{
		dragCounter++;
	}
	public void setCounterMinusOne()
	{
		dragCounter--;
	}
	
	/**
	 * returns the selection shape created for the given Mode m
	 * @param m
	 * @return
	 */
	public Shape getSelectionShape(Mode m)
	{
		return getSelectionShape(m, null);
	}
	
	public Shape getSelectionShape(Mode m, Collection<Point> points)
	{
		switch (m)
		{
		case Rectangle:
		case Text:
			selectionShape = new Rectangle(1, 1, DRAW_COLOR);
			break;
		case Ellipse:
			selectionShape = new Ellipse(1, 1);
			selectionShape.setFill(DRAW_COLOR);
			break;
		case Line:
			selectionShape = new Line(1, 1, 0, 0);
			selectionShape.setFill(DRAW_COLOR);
			selectionShape.setStrokeWidth(strokeWidth.doubleValue());
			break;
		default:
			selectionShape = null;
			break;
		case Triangle:
			selectionShape = new Polygon();
			selectionShape.setFill(DRAW_COLOR);
			selectionShape.setStroke(DRAW_COLOR);
			selectionShape.setStrokeWidth(2);
			for (Point p : points)
			{
				((Polygon)selectionShape).getPoints().addAll(p.getX(), p.getY());
			}
			break;
		}
		return selectionShape;
	}
	
	public Shape getSelectionShape()
	{
		return selectionShape;
	}
	
	/**
	 * Returns the foreground-color set by the EU
	 * @return
	 */
	public Paint getForeColor()
	{
		return foreColor;
	}
	
	/**
	 * Returns the background color set by the EU
	 * @return
	 */
	public Paint getBackColor()
	{
		return backColor;
	}
	
	// ========== Triangles
	public ArrayList<Point> trianglePoints()
	{
		return trianglePoints;
	}
	public void addTrianglePoint(Point p)
	{
		trianglePoints.add(p);
	}
	public int getTrianglePointCount()
	{
		return trianglePoints.size();
	}
	
	private DoubleProperty strokeWidth;
	public double getStrokeWidth()
	{
		return strokeWidth.doubleValue();
	}
	public void setStrokeWidth(double width)
	{
		strokeWidth.set(width);
	}
	public DoubleProperty strokeWidthProperty()
	{
		return strokeWidth;
	}
}
